package com.huxiu.yd;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.VolleyError;
import com.google.gson.Gson;
import com.huxiu.yd.net.GsonRequest;
import com.huxiu.yd.net.NetworkConstants;
import com.huxiu.yd.net.responses.BaseResponse;
import com.huxiu.yd.net.responses.ProfileResponse;
import com.huxiu.yd.utils.Constants;
import com.huxiu.yd.utils.ErrorResponseException;
import com.huxiu.yd.utils.Global;
import com.huxiu.yd.utils.HttpUtil;
import com.huxiu.yd.utils.LogUtils;
import com.huxiu.yd.utils.Settings;
import com.huxiu.yd.utils.Utils;
import com.sina.weibo.sdk.auth.AuthInfo;
import com.sina.weibo.sdk.auth.Oauth2AccessToken;
import com.sina.weibo.sdk.auth.WeiboAuthListener;
import com.sina.weibo.sdk.auth.sso.SsoHandler;
import com.sina.weibo.sdk.exception.WeiboException;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.WXAPIFactory;
import com.tencent.tauth.IUiListener;
import com.tencent.tauth.Tencent;
import com.tencent.tauth.UiError;

import org.json.JSONException;
import org.json.JSONObject;

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;


/**
 * Created by tian on 14-9-20:下午10:14.
 */
public class AuthenticatorActivity extends BaseActivity implements WeiboAuthListener, IUiListener {

    public static final int EXISTED_USER_ERROR = 2005;

    private static final String TAG = AuthenticatorActivity.class.getName();

    protected static final String VALUE_HUXIU = "huxiu";

    protected static final String VALUE_SINA = "2";

    protected static final String VALUE_QQ = "3";

    protected static final String KEY_TOKEN = "token";

    protected static final String KEY_OPEN_ID = "openid";

    protected static final String KEY_USERNAME = "username";

    protected static final String KEY_PASSWORD = "password";

    protected static final String KEY_EMAIL = "email";

    protected static final int REQUEST_CODE_BIND_OR_REGISTER = 1;

    protected static final int REQUEST_CODE_COMPLETE_INFO = 2;

    protected AuthInfo mWeiboAuth;

    protected Oauth2AccessToken accessToken;

    protected SsoHandler mSsoHandler;

    protected Tencent mTencent;

    private String errorMsg;

    protected IWXAPI mWechatApi;

    public boolean forBind = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        forBind = getIntent().getBooleanExtra("Bind", false);
        initTencent();
        initWeibo();
        initWeixin();
        LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
        lbm.registerReceiver(mReciver, new IntentFilter(Constants.ACTION_WECHAT_LOGIN));
    }

    BroadcastReceiver mReciver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getBooleanExtra("result", false)) {
                String code = intent.getStringExtra("code");
                getWeixinToken(code);
            } else {
                Toast.makeText(AuthenticatorActivity.this, getString(R.string.log_in_failed), Toast.LENGTH_SHORT).show();
            }
        }
    };


    public void getWeixinToken(final String code) {
        new AsyncTask<Void, Void, Void>() {
            String resultData = null;

            @Override
            protected Void doInBackground(Void... s) {
                HashMap<String, Object> params = new HashMap<String, Object>();
                params.put("appid", Constants.WECHAT_KEY);
                params.put("secret", Constants.WECHAT_SECRECT);
                params.put("code", code);
                params.put("grant_type", "authorization_code");
                resultData = HttpUtil.get("https://api.weixin.qq.com/sns/oauth2/access_token", params);
                return null;
            }

            @Override
            protected void onPostExecute(Void aVoid) {
                super.onPostExecute(aVoid);
                String openid = null;
                String token = null;
                if (resultData != null) {
                    try {
                        JSONObject json = new JSONObject(resultData);
                        openid = json.getString("openid");
                        token = json.getString("access_token");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
                if (TextUtils.isEmpty(openid)) {
                    Toast.makeText(AuthenticatorActivity.this, getString(R.string.log_in_failed), Toast.LENGTH_SHORT).show();
                } else {
                    Settings.setWeixinUid(openid);
                    Settings.setWeixinToken(token);
                    if (AuthenticatorActivity.this instanceof LogInActivity || AuthenticatorActivity.this instanceof RegisterActivity) {
                        Map<String, String> params = new LinkedHashMap<>();
                        params.put("act", "login");
                        params.put("login_type", "weixin");
                        params.put("openid", openid);
                        params.put("token", token);
                        doLogIn(params);
                    } else if (AuthenticatorActivity.this instanceof BindAccountsActivity) {
                        Map<String, String> params = new LinkedHashMap<>();
                        params.put("act", "user_bind");
                        params.put("bind_type", "weixin");
                        params.put("token", token);
                        params.put("openid", openid);
                        params.put("operation_type", "bind");
                        doBind(params);
                    }
                }
            }
        }.execute();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
        lbm.unregisterReceiver(mReciver);
    }

    private void initWeixin() {
        mWechatApi = WXAPIFactory.createWXAPI(this, Constants.WECHAT_KEY);
    }

    protected void initTencent() {
        try {
            mTencent = Tencent.createInstance(Constants.TENCENT_APP_ID, this);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    protected void initWeibo() {
        mWeiboAuth = new AuthInfo(this, Constants.SINA_APP_KEY, Constants.SINA_APP_REDIRECT_URI,
                Constants.SINA_SCOPE);
        mSsoHandler = new SsoHandler(this, mWeiboAuth);
    }


    @Override
    public void onComplete(Object o) {
        JSONObject object = (JSONObject) o;
        try {
            LogUtils.d(TAG, "onTencentComplete, object is " + object.toString());
            String token = object.optString("access_token");
            String openId = object.optString("openid");
            String expireTime = object.optString("expires_in");
            Oauth2AccessToken qqAccessToken = new Oauth2AccessToken(token, expireTime);
            if (qqAccessToken.isSessionValid()) {
                String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new java.util.Date
                        (qqAccessToken
                                .getExpiresTime()));
                LogUtils.d(TAG, "QQ log in, expire date is " + date);
                Settings.saveQQAccessToken(qqAccessToken);
                Settings.saveQQUid(openId);
            }
            Settings.saveQQLogInfo(object.toString());
            if (AuthenticatorActivity.this instanceof LogInActivity || AuthenticatorActivity.this instanceof RegisterActivity) {
                Map<String, String> params = new LinkedHashMap<>();
                params.put("act", "login");
                params.put("login_type", "qq");
                params.put("openid", openId);
                params.put("token", token);
                doLogIn(params);
            } else if (AuthenticatorActivity.this instanceof BindAccountsActivity) {
                Map<String, String> params = new LinkedHashMap<>();
                params.put("act", "user_bind");
                params.put("bind_type", "qq");
                params.put("token", token);
                params.put("openid", openId);
                params.put("operation_type", "bind");
                doBind(params);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onError(UiError uiError) {
        LogUtils.d(TAG,
                "onError, uiError is " + uiError.errorDetail + ", " + uiError.errorMessage);
        Toast.makeText(this,
                TextUtils.isEmpty(uiError.errorMessage) ? getString(R.string.qq_log_in_failed)
                        : uiError.errorMessage, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onComplete(Bundle bundle) {
        try {
            accessToken = Oauth2AccessToken.parseAccessToken(bundle);
            LogUtils.d(TAG,
                    "onComplete, accessToken is " + accessToken.getUid() + ":" + accessToken
                            .getToken() + ", expireTime is " + accessToken.getExpiresTime());
            if (accessToken.isSessionValid()) {
                Settings.saveWeiboAccessToken(accessToken);
                Settings.saveWeiboUid(accessToken.getUid());
                if (this instanceof LogInActivity || this instanceof RegisterActivity) {
                    Map<String, String> params = new LinkedHashMap<>();
                    params.put("act", "login");
                    params.put("login_type", "weibo");
                    params.put("openid", accessToken.getUid());
                    params.put("token", accessToken.getToken());
                    doLogIn(params);
                } else if (this instanceof BindAccountsActivity) {
                    Map<String, String> params = new LinkedHashMap<>();
                    params.put("act", "user_bind");
                    params.put("bind_type", "weibo");
                    params.put("token", accessToken.getToken());
                    params.put("openid", accessToken.getUid());
                    params.put("operation_type", "bind");
                    doBind(params);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(this, getString(R.string.log_in_failed), Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onWeiboException(WeiboException e) {
        LogUtils.d(TAG, "e.message is " + e.getLocalizedMessage());
        e.printStackTrace();
        Toast.makeText(this, String.format(getString(R.string.weibo_error), e.getMessage()),
                Toast.LENGTH_LONG).show();
    }

    @Override
    public void onCancel() {
        LogUtils.d(TAG, "SSO cancelled!!!");
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if ((requestCode == REQUEST_CODE_BIND_OR_REGISTER
                || requestCode == REQUEST_CODE_COMPLETE_INFO) && resultCode == RESULT_OK) {
            setResult(RESULT_OK);
            finish();
            return;
        }
        // sso 授权回调
        try {
            if (mSsoHandler != null) {
                mSsoHandler.authorizeCallBack(requestCode, resultCode, data);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void doBind(Map<String, String> params) {
        final boolean isBind = params.get("operation_type").equals("bind");
        final String type = params.get("bind_type");
        GsonRequest<BaseResponse> request = new GsonRequest<>(
                NetworkConstants.MEMBER_URL, Request.Method.POST, BaseResponse.class,
                true, params, new Response.Listener<BaseResponse>() {
            @Override
            public void onResponse(BaseResponse response) {
                dismissProgress();
                if (response.isSuccess()) {
                    if (isBind) {
                        Utils.showToast(R.string.bind_success);
                    } else {
                        Utils.showToast(R.string.unbind_success);
                        switch (type) {
                            case "weibo":
                                Settings.clearSinaLogInInfo();
                                break;
                            case "qq":
                                Settings.clearQQLogInInfo();
                                break;
                            case "huxiu":
                                Settings.setHxUserId("");
                                break;
                            case "weixin":
                                Settings.setWeixinUid("");
                                break;
                        }
                    }
                    updateUI();
                }
            }
        }, mErrorListener);
        mQueue.add(request);
//        mQueue.start();
    }

    protected void updateUI() {
    }

    protected void doLogIn(Map<String, String> params) {
        GsonRequest<ProfileResponse> request = new GsonRequest<>(
                NetworkConstants.MEMBER_URL, Request.Method.POST, ProfileResponse.class,
                false, params, new Response.Listener<ProfileResponse>() {
            @Override
            public void onResponse(ProfileResponse response) {
                dismissProgress();
                if (response.isSuccess()) {
                    Settings.saveProfile(response.data.toString());
                    Global.setUser(response.data);
                    Utils.showToast(R.string.log_in_success);
                    LocalBroadcastManager.getInstance(App.getInstance()).sendBroadcast(new Intent(
                            Constants.INTENT_USER_LOGGED_IN));
                    setResult(RESULT_OK);
                    finish();
                }
            }
        }, mErrorListener);
        mQueue.add(request);
//        mQueue.start();
    }

    protected ErrorListener mErrorListener = new ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            dismissProgress();
            Throwable t = error.getCause();
            if (t instanceof ErrorResponseException) {
                if (AuthenticatorActivity.this instanceof LogInActivity
                        || AuthenticatorActivity.this instanceof HuxiuLogInActivity) {
                    LogUtils.d(TAG, "t.result is " + ((ErrorResponseException) t).result);
                    if (((ErrorResponseException) t).result == 2) {
                        if (forBind) {
                            ProfileResponse resp = new Gson().fromJson(((ErrorResponseException) t).data, ProfileResponse.class);
                            if (forBind) {
                                Intent data = new Intent();
                                data.putExtra("openid", resp.data.openid);
                                data.putExtra("token", resp.data.token);
                                setResult(RESULT_OK, data);
                                finish();
                                return;
                            }
                        }
                        startActivityForResult(
                                new Intent(AuthenticatorActivity.this, RegisterActivity.class),
                                REQUEST_CODE_BIND_OR_REGISTER);
                    } else {
                        Utils.showToast(error.getMessage());
                    }
                } else {
                    Utils.showToast(error.getMessage());
                }
            } else {
                Utils.showToast(R.string.generic_failure);
            }
        }
    };
}
